<?php

class Jwawa_Db_Statement_Pdo_Mysql extends Zend_Db_Statement_Pdo
{
    protected $log;
//    protected $_fetchMode = PDO::FETCH_BOUND;
    protected $pdoDataTypeMap = array(
        'TINY' => PDO::PARAM_INT,
        'SHORT' => PDO::PARAM_INT,
        'INT24' => PDO::PARAM_INT,
        'LONG' => PDO::PARAM_INT,
        'LONGLONG' => PDO::PARAM_INT,
        'FLOAT' => array('pdoKey' => PDO::PARAM_STR, 'castFunc' => 'floatval'),
        'DOUBLE' => array('pdoKey' => PDO::PARAM_STR, 'castFunc' => 'floatval'),
        'NEWDECIMAL' => array('pdoKey' => PDO::PARAM_STR, 'castFunc' => 'floatval'),
        'TIME' => PDO::PARAM_STR,
        'DATE' => PDO::PARAM_STR,
        'DATETIME' => PDO::PARAM_STR,
        'TIMESTAMP' => PDO::PARAM_INT,
        'STRING' => PDO::PARAM_STR,
        'VAR_STRING' => PDO::PARAM_STR,
        'TINY_BLOB' => PDO::PARAM_LOB,
        'BLOB' => PDO::PARAM_LOB,
        'MEDIUM_BLOB' => PDO::PARAM_LOB,
        'LONG_BLOB' => PDO::PARAM_LOB,
        'BIT' => PDO::PARAM_INT
    );

    function __construct($adapter, $sql)
    {
        $this->log = Zend_Registry::get('log');
        parent::__construct($adapter, $sql);
    }

//    public function fetch($style = null, $cursor = null, $offset = null)
//    {
//        if($style == null){
//            $columnCount = $this->columnCount();
//            $result = array();
//            for($i = 0; $i < $columnCount; $i++){
//                $columnMeta = $this->getColumnMeta($i);
//                $paramType = $this->pdoDataTypeMap[$columnMeta['native_type']];
//                $columnName = $columnMeta['name'];
//                $result[$columnName] = null;
//
//                $this->bindColumn($i + 1, $result[$columnName], $paramType);
//            }
//            if ($row = parent::fetch($style, $cursor, $offset)){
//                return $result;
//            } else {
//                return $row;
//            }
//        } else {
//            return parent::fetch($style, $cursor, $offset);
//        }
//    }

//    public function fetchAll($style = null, $col = null)
//    {
//        if ($style == null){
//            $resultList = array();
//            while($row = $this->fetch($style)){
//                array_push($resultList, $row);
//            }
//
//            return $resultList;
//        } else {
//            return parent::fetchAll($style, $col);
//        }
//    }

    public function &fetchAllObj($class = null){
//        $allRow = $this->fetchAll(PDO::FETCH_OBJ);
//        $rst = array();
//        foreach($allRow as $row){
//            array_push($rst, new $class($row));
//        }
//
//        return $rst;

            $resultList = array();
            while($row = $this->fetchObj($class)){
                array_push($resultList, $row);
            }

            return $resultList;
    }

    public function fetchObj($class = null){
//        $row = $this->fetch(PDO::FETCH_OBJ);
//        return new $class($row);

        $columnCount = $this->columnCount();
        if($class !== null){
            if(is_subclass_of($class, 'Jwawa_BaseModel')){
                $result = new stdClass();
            } else{
                $result = new $class();
            }
        } else {
            $result = new stdClass();
        }

        $castMap = array();
        for($i = 0; $i < $columnCount; $i++){
            $columnMeta = $this->getColumnMeta($i);
            $columnName = $columnMeta['name'];
            $paramType = $this->pdoDataTypeMap[$columnMeta['native_type']];
            if(is_int($paramType)){
                $bindType = $paramType;
            } else {
                $bindType = $paramType['pdoKey'];
                $castMap[$columnName] = $paramType['castFunc'];
            }

            $result->$columnName = null;
            $this->bindColumn($i + 1, $result->$columnName, $bindType);
        }

        if ($row = parent::fetch()){
            foreach($castMap as $att => $castFunc){
                $result->$att = $castFunc($result->$att);
            }
            if(is_subclass_of($class, 'Jwawa_BaseModel')){
                $result = new $class($result);
            }

            return $result;
        } else {
            return $row;
        }
    }

    public function setProperties($props){
        $sql = $this->getDriverStatement()->queryString;
        preg_match_all('/:(\w+)/', $sql, $matches);

        if(!$matches){
            throw new Exception('Set properties for statement error. Not found parameter need to be set.');
        }

        $isSingleParam = true;
        if(is_array($matches[0])){
            $isSingleParam = false;
        }

        if($isSingleParam){
            $matchParam =  $matches[1];
            if(is_array($props)){
                $this->bindValue($matchParam, $props[$matchParam]);
            } else if(is_object($props)){
                $this->bindValue($matchParam, $props->$matchParam);
            }
        } else {
            $matchParamList = $matches[1];
            for($i = 0; $i < count($matchParamList); $i++){
                if(is_array($props)){
                    $param = $matchParamList[$i];
                    $this->bindValue($matchParamList[$i], $props[$param]);
                } else if(is_object($props)){
                    $param = $matchParamList[$i];
                    $this->bindValue($matchParamList[$i], $props->$param);
                }
            }
        }
    }
}
